﻿/*                       NOTICE
 * 
 * This software was produced for the U. S. Government
 * under Contract No. FA8721-10-C-0001, and is
 * subject to the Rights in Noncommercial Computer Software
 * and Noncommercial Computer Software Documentation Clause
 * (DFARS) 252.227-7014 (JUN 1995)
 * 
 * Approved for Public Release: 11-2435
 * © 2011 The MITRE Corporation. All Rights Reserved. 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */



using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Timers;
using InputManager;
using GestureListenerClient.Services.Delegates;
using GestureListenerClient.Services;
using System.Windows.Forms;

namespace GestureControlOfWindowsForm
{
    class WorldWindProfile : ApplicationProfile
    {
        private ControlForm windowsControl;
        private System.Timers.Timer zoomTimer;
        private int cursorID = -1;
        private bool zoomIn;
        private PointF anchor;

        public WorldWindProfile(ControlForm windowsControl)
        {
            this.windowsControl = windowsControl;
            zoomTimer = new System.Timers.Timer(1000);
            zoomTimer.Elapsed += new ElapsedEventHandler(zoomTimer_Tick);
        }

        void zoomTimer_Tick(object sender, EventArgs e)
        {
            if(zoomIn)
                Mouse.Scroll(Mouse.ScrollDirection.Up);
            else
                Mouse.Scroll(Mouse.ScrollDirection.Down);
        }

        public void setListener(GestureClient listener)
        {
            SlideGestureDelegate slideGestureDelegate = new SlideGestureDelegate();
            HoldSlideGestureDelegate holdSlideGestureDelegate = new HoldSlideGestureDelegate();
            ZoomGestureDelegate zoomGestureDelegate = new ZoomGestureDelegate();
            TapGestureDelegate tapGestureDelegate = new TapGestureDelegate();
            //HoldGestureDelegate holdGestureDelegate = new HoldGestureDelegate();
            DragGestureDelegate dragGestureDelegate = new DragGestureDelegate();

            FiducialObjectDelegate fiducial = new FiducialObjectDelegate();
            fiducial.OnObjectAdded += new FiducialCallbackDelegate.OnFiducialDelegate(fiducial_OnObjectAdded);
            fiducial.OnObjectRemoved += new FiducialCallbackDelegate.OnFiducialDelegate(fiducial_OnObjectRemoved);

            holdSlideGestureDelegate.OnHoldSlideStart += new GestureCallbackDelegate.OnGestureDelegate(holdSlideGestureDelegate_OnHoldSlideStart);
            holdSlideGestureDelegate.OnHoldSlideChange += new GestureCallbackDelegate.OnGestureDelegate(holdSlideGestureDelegate_OnHoldSlideChange);
            holdSlideGestureDelegate.OnHoldSlideEnd += new GestureCallbackDelegate.OnGestureDelegate(holdSlideGestureDelegate_OnHoldSlideEnd);

            slideGestureDelegate.OnSlideChange += new GestureCallbackDelegate.OnGestureDelegate(slideGestureDelegate_OnSlideChange);

            tapGestureDelegate.OnTap += new GestureCallbackDelegate.OnGestureDelegate(tapGestureDelegate_OnTap);
            tapGestureDelegate.OnDoubleTap += new GestureCallbackDelegate.OnGestureDelegate(tapGestureDelegate_OnDoubleTap);

            zoomGestureDelegate.OnZoomStart += new GestureCallbackDelegate.OnGestureDelegate(zoomGestureDelegate_OnZoomStart);
            zoomGestureDelegate.OnZoomChange += new GestureCallbackDelegate.OnGestureDelegate(zoomGestureDelegate_OnZoomChange);
            zoomGestureDelegate.OnZoomEnd += new GestureCallbackDelegate.OnGestureDelegate(zoomGestureDelegate_OnZoomEnd);

            dragGestureDelegate.OnDragStart += new GestureCallbackDelegate.OnGestureDelegate(dragGestureDelegate_OnDragStart);
            dragGestureDelegate.OnDragChange += new GestureCallbackDelegate.OnGestureDelegate(dragGestureDelegate_OnDragChange);
            dragGestureDelegate.OnDragEnd += new GestureCallbackDelegate.OnGestureDelegate(dragGestureDelegate_OnDragEnd);

            listener.registerListener(new ListenerRegistration("Slide Listener", new System.Drawing.RectangleF(-2, -2, 4, 4), slideGestureDelegate));
            listener.registerListener(new ListenerRegistration("HoldSlide Listener", new System.Drawing.RectangleF(-2, -2, 4, 4), holdSlideGestureDelegate));
            listener.registerListener(new ListenerRegistration("Tap Listener", new System.Drawing.RectangleF(-2, -2, 4, 4), tapGestureDelegate));
            listener.registerListener(new ListenerRegistration("Zoom Listener", new System.Drawing.RectangleF(-2, -2, 4, 4), zoomGestureDelegate));
            listener.registerListener(new ListenerRegistration("Drag Listener", new System.Drawing.RectangleF(-2, -2, 4, 4), dragGestureDelegate));
        }

        public void moveMouse(PointF point)
        {
            Console.WriteLine((int)(windowsControl.offsetX + (point.X * windowsControl.width)) + ", " +
                (int)(windowsControl.offsetY + (point.Y * windowsControl.height)));
            Mouse.Move((int)(windowsControl.offsetX + (point.X * windowsControl.width)),
                (int)(windowsControl.offsetY + (point.Y * windowsControl.height)));
        }

        public void fiducial_OnObjectAdded(object source, FiducialArgs e)
        { }

        public void fiducial_OnObjectUpdated(object source, FiducialArgs e)
        { }

        public void fiducial_OnObjectRemoved(object source, FiducialArgs e)
        { }

        public void tapGestureDelegate_OnTap(object source, GestureArgs e)
        {
            moveMouse(e.Gesture.Coords[0]);
            Console.WriteLine("Click");
            Mouse.PressButton(Mouse.MouseKeys.Left, 0);
        }

        public void tapGestureDelegate_OnHold(object source, GestureArgs e)
        { }

        public void tapGestureDelegate_OnDoubleTap(object source, GestureArgs e)
        {
            Mouse.ButtonUp(Mouse.MouseKeys.Right);
        }

        public void zoomGestureDelegate_OnZoomStart(object source, GestureArgs e)
        {
            zoomTimer.Start();
        }

        public void zoomGestureDelegate_OnZoomChange(object source, GestureArgs e)
        {
            float magnitude = e.Gesture.Coords[0].X;
            zoomIn = magnitude < 0 ? false : true;
            zoomTimer.Interval = Math.Max(50, (int)((0.5 - Math.Abs(magnitude) * 3 * windowsControl.zoomSpeed) * 1000));
        }

        public void zoomGestureDelegate_OnZoomEnd(object source, GestureArgs e)
        {
            zoomTimer.Stop();
        }

        public void holdSlideGestureDelegate_OnHoldSlideStart(object source, GestureArgs e)
        {
            Mouse.ButtonUp(Mouse.MouseKeys.Left);
            anchor.X = e.Gesture.Coords[0].X;
            anchor.Y = e.Gesture.Coords[0].Y;
            moveMouse(e.Gesture.Coords[0]);
            Mouse.ButtonDown(Mouse.MouseKeys.Right);
        }

        public void holdSlideGestureDelegate_OnHoldSlideChange(object source, GestureArgs e)
        {
            float deltaY = e.Gesture.Coords[0].Y;
            float newY = anchor.Y + (windowsControl.isYInverted() ? -deltaY : deltaY);
            moveMouse(new PointF(anchor.X + e.Gesture.Coords[0].X, newY));
        }

        public void holdSlideGestureDelegate_OnHoldSlideEnd(object source, GestureArgs e)
        {
            Mouse.ButtonUp(Mouse.MouseKeys.Right);
        }

        public void slideGestureDelegate_OnSlideStart(object source, GestureArgs e)
        {
            if (cursorID == -1)
                cursorID = e.Gesture.ID;
        }

        public void slideGestureDelegate_OnSlideChange(object source, GestureArgs e)
        {
            if (cursorID == e.Gesture.ID)
                moveMouse(e.Gesture.Coords[0]);
        }

        public void slideGestureDelegate_OnSlideEnd(object source, GestureArgs e)
        {
            if (cursorID == e.Gesture.ID)
                cursorID = -1;
        }

        public void dragGestureDelegate_OnDragStart(object source, GestureArgs e)
        {
            moveMouse(e.Gesture.Coords[0]);
            Mouse.ButtonDown(Mouse.MouseKeys.Left);
        }

        public void dragGestureDelegate_OnDragChange(object source, GestureArgs e)
        {
            moveMouse(e.Gesture.Coords[0]);
        }

        public void dragGestureDelegate_OnDragEnd(object source, GestureArgs e)
        {
            moveMouse(e.Gesture.Coords[0]);
            Mouse.ButtonUp(Mouse.MouseKeys.Left);
        }
    }
}
